﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using YAPL.Language.Core;
using YAPL.Language.Core.Types;
using YAPL.Util;

namespace YAPL.Language.Compiler.CodeGen.ReflectionEmitGenerator.AstGen.Helpers {
	public static class ILGeneratorYAPLObjectExtensions {
		/// <summary>
		/// Gets instance variable from object scope. Object should be on top of evaluation stack
		/// </summary>
		/// <param name="ilGen">IL Generator provided</param>
		/// <param name="key">variable name</param>
		public static void EmitGetInstanceVariableFromObjectScope(this ILGenerator ilGen, string key) {
			var getInstanceVariablesMethod = typeof (YAPLObject).GetProperty("InstanceVariables").GetGetMethod();
			var getItemMethod = typeof(Scope).GetIndexerGetMethod(new[] { typeof(String) });
			ilGen.Emit(OpCodes.Callvirt, getInstanceVariablesMethod);
			ilGen.Emit(OpCodes.Ldstr, key);
			ilGen.Emit(OpCodes.Callvirt, getItemMethod);
		}

		/// <summary>
		/// Sets instance variable from object scope. Object should be on top of evaluation stack
		/// </summary>
		/// <param name="ilGen">IL Generator provided</param>
		/// <param name="key">variable name</param>
		public static void EmitSetInstanceVariable(this ILGenerator ilGen, string key) {
			var setItemMethod = typeof(Scope).GetIndexerSetMethod(new[] { typeof(String) });
			var getInstanceVariablesMethod = typeof(YAPLObject).GetProperty("InstanceVariables").GetGetMethod();
			ilGen.Emit(OpCodes.Callvirt, getInstanceVariablesMethod);
			ilGen.Emit(OpCodes.Ldstr, key);
			ilGen.Emit(OpCodes.Ldloc_0);
			ilGen.Emit(OpCodes.Callvirt, setItemMethod);
			ilGen.Emit(OpCodes.Ldloc_0);
		}

		public static void EmitCreateDynamicClass(this ILGenerator ilGen) {
			var method = typeof (YAPLObject).GetMethod("CreateDynamicClass");
			ilGen.Emit(OpCodes.Callvirt, method);
		}
	}
}
